package com.scs.application.modules.wm.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.*;
import com.scs.application.modules.base.dto.ExportHeadDTO;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.mapper.MatrUnitMapper;
import com.scs.application.modules.base.service.*;
import com.scs.application.modules.base.util.MatrPassUtil;
import com.scs.application.modules.cfg.utils.ParameterUtils;
import com.scs.application.modules.purchase.entity.OrderItem;
import com.scs.application.modules.purchase.service.OrderItemService;
import com.scs.application.modules.wm.dto.DeliveryDTO;
import com.scs.application.modules.wm.dto.OrthWiDTO;
import com.scs.application.modules.wm.dto.OrthWiItemDTO;
import com.scs.application.modules.wm.dto.StockByPackTempDTO;
import com.scs.application.modules.wm.entity.OrderBarcode;
import com.scs.application.modules.wm.entity.WorkOrder;
import com.scs.application.modules.wm.entity.WorkOrderItem;
import com.scs.application.modules.wm.mapper.InOrderItemMapper;
import com.scs.application.modules.wm.service.InOrderItemService;
import com.scs.application.modules.wm.service.OrderBarcodeService;
import com.scs.application.modules.wm.service.WorkOrderService;
import com.scs.application.utils.ExportHeadDTONew;
import com.scs.application.utils.ImportResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 入库单明细 服务实现类
 * </p>
 */
@Slf4j
@Service
public class InOrderItemServiceImpl extends BaseServiceImpl<InOrderItemMapper, WorkOrderItem> implements InOrderItemService {

    @Value("${res.real-path}")
    protected String resPath;

    @Autowired
    private MatrService matrService;

    @Autowired
    private OrderBarcodeService orderBarcodeService;

    @Autowired
    private WorkOrderService workOrderService;

    @Autowired
    private PackTempletItemService packTempletItemService;

    @Autowired
    private PackTempletService packTempletService;

    @Autowired
    private LocationService locationService;

    @Autowired
    private LocationLimitMatrService locationLimitMatrService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private MatrPassUtil matrPassUtil;

    @Resource
    private InOrderItemMapper inOrderItemMapper;


    @Autowired
    private MatrUnitMapper matrUnitMapper;
    /**
     * 根据送货单明细保存送货单明细
     *
     * @param deliveryDTOItemList
     * @param workOrderId
     * @param qrCodeInOrder 是否二维码入库，如果是的话，需要检查是否重复入库
     * @return
     */
    @Override
    public List<WorkOrderItem> saveOrderItemByDelivery(List<DeliveryDTO.DeliveryItemDTO> deliveryDTOItemList, String workOrderId, String warehouseId, boolean qrCodeInOrder,DeliveryDTO deliveryDTO) {
        if (deliveryDTOItemList == null || deliveryDTOItemList.size() == 0) {
            return null;
        }
        List<WorkOrderItem> workOrderItemListAdd = new ArrayList<>();
        deliveryDTOItemList.forEach(item -> {
            BusinessException.throwErrorIf(StringUtils.isBlank(item.getMaterialCode()), "该商品[%s]尚未同步，请先从供应商平台同步该商品信息",item.getMaterialName());
            Matr matr = matrService.getOne(new QueryWrapper<Matr>().eq("mscm_code", item.getMaterialCode()),false);
            BusinessException.throwErrorIf(ObjectUtil.isNull(matr), "该商品[%s]未找到，请先从供应商平台同步该商品信息",item.getMaterialName());

            WorkOrderItem workOrderItem = new WorkOrderItem();
            Location location = locationLimitMatrService.getSuitLocation(warehouseId, matr.getId(),item.getOrderUnit());
            if (qrCodeInOrder) { //仅在二维码入库时进行判断，以免影响正常入库的效率
                WorkOrderItem existWorkOrderItem = this.getOne(new QueryWrapper<WorkOrderItem>().eq("work_order_id", workOrderId).eq("po_item_id", item.getSourceKey()));
                if(existWorkOrderItem != null) { //已入库，不能重复扫描
                    throw new BusinessException("该二维码入库单已经扫描入库，不能重复扫描");
                }
            }
            workOrderItem.setAmount(item.getSubtotalAmount())
                    .setCertificateNo(item.getCertificateNo())
                    .setExpDate(DateUtils.parse(item.getExpiredDate()))
                    .setMatrId(matr.getId())
                    .setMfgDate(DateUtils.parse(item.getProductionDate()))
                    .setMatrName(item.getMaterialName())
                    .setMatrSpec(item.getMaterialSpec())
                    .setLot(item.getLot() == null ? "" : item.getLot())
                    .setPackageUnit(item.getOrderUnit())
                    .setPackageQty(item.getQty() / item.getOrderQty())
                    .setSkuPriceSp(item.getPrice())
                    .setSkuPrice(item.getPrice())
                    .setSkuQty(item.getQty())
                    .setSkuUnit(item.getUnit())
                    .setLocationId(location.getId())
                    .setLocationName(location.getName())
                    .setMfgName(item.getManufacturerName())
                    .setSterilizationDate(DateUtils.parse(item.getSterilizationDate()))
                    .setWorkOrderId(workOrderId)
                    .setPoItemId(item.getSourceKey())
                    .setMfgSn(item.getMfgSn())
                    .setUdi(item.getUdi() != null? item.getUdi() : "")
                    .setHisMedicareNo(matr.getHisMedicareNo());

            if (!GlobalConsts.PO_FROM_TYPE_SCP.equals(deliveryDTO.getFromType())) {
                OrderItem orderItem = orderItemService.getOne(new QueryWrapper<OrderItem>().eq("id",item.getSourceKey()));
                BusinessException.throwErrorIf(ObjectUtil.isNull(orderItem), "该商品[%s]未找到相关采购明细，请联系运营人员",item.getMaterialName());
                workOrderItem.setFlagTemporaryPurchase(orderItem.getFlagTemporaryPurchase());
            }

            //skuPrice取耗材实时价格
            workOrderItem.setSkuPrice(matr.getSkuPrice());
            workOrderItem.setAmount(UtilNum.getDouble(matr.getSkuPrice()*workOrderItem.getSkuQty()));
            super.save(workOrderItem);
            workOrderItemListAdd.add(workOrderItem);

            //保存送货单SN列表
            if (item.getSns() != null && item.getSns().length > 0) {
               if (workOrderItem.getSkuQty()!=item.getSns().length){
                   throw new BusinessException("该送货单明细数量和生成SN不匹配无法入库,请联系供应商平台管理员");
               }
                if (item.getListSnUdi() != null && item.getListSnUdi().size() > 0) {
                    List<OrderBarcode> list = new ArrayList<>();
                    for(DeliveryDTO.DeliveryItemDTO.SnUdiDTO dto : item.getListSnUdi()){
                        OrderBarcode orderBarcode = new OrderBarcode();
                        orderBarcode.setWorkOrderId(workOrderId)
                                .setWorkOrderItemId(workOrderItem.getId())
                                .setSn(dto.getSn())
                                .setRfid("")
                                .setUdi(dto.getUdi()!=null? dto.getUdi():"");
                        list.add(orderBarcode);
                    }
                    orderBarcodeService.saveBatch(list);
                }
                /*orderBarcodeService.saveBatch(Arrays.stream(item.getSns())
                        .map(sn -> new OrderBarcode(workOrderId, workOrderItem.getId(), sn, "",""))
                        .collect(Collectors.toList()));*/
            }
        });
        return workOrderItemListAdd;
    }



    /**
     * 根据出库单明细生成入库单明细
     *
     * @param outWorkOrderItemList
     * @param workOrderId
     * @param warehouseId
     * @param locationId  不传则找物理仓库该耗材的默认默认库位
     */
    @Override
    public void saveOrderItemByOutOrder(List<WorkOrderItem> outWorkOrderItemList, String workOrderId, String warehouseId,String locationId) {

        if (outWorkOrderItemList == null || outWorkOrderItemList.size() == 0) {
            return;
        }
        List<WorkOrderItem> workOrderItemList = new ArrayList<>();

        outWorkOrderItemList.forEach(item -> {
            Location location;
            if(StringUtils.isNotBlank(locationId)){
                location=locationService.getById(locationId);
                if(location==null) throw new BusinessException("未找到指定库位，库位ID【"+locationId+"】");
            }else{
                location = locationLimitMatrService.getSuitLocation(warehouseId, item.getMatrId(),item.getPackageUnit());
            }
            WorkOrderItem inWorkOrderItem = new WorkOrderItem();
            BeanUtils.copyProperties(item, inWorkOrderItem);
            inWorkOrderItem.setId(null);
            inWorkOrderItem.setWorkOrderId(workOrderId)
                    .setLocationId(location.getId())
                    .setLocationName(location.getName());
            workOrderItemList.add(inWorkOrderItem);

            /**
             * @Description： ？？？ 将出库单库存设置成0？
             * <Pre>
             *     下面这几行代码为变更集 880 版本加入的，目的不明。
             *     saveOrderItemByOutOrder方法是根据出库单明细生成入库单明细，来源仓库出多少，目的仓库就入多少。
             *     以下代码将包装数量和包装单品数量改成0,又没有修改amount字段，故此产生脏数据。
             *     引用该方法的服务类 OprtCheckServiceImpl、TransferServiceImpl
             * </Pre>
             * @Author wyt
             * @Date 2020/9/26
             */
           /* //将出库单库存设置成0
            WorkOrderItem outWorkOrderItem = super.getById(item.getId());
            outWorkOrderItem.setPackageQty(0d).setSkuQty(0d);
            workOrderItemList.add(outWorkOrderItem);*/
        });

        super.saveOrUpdateBatch(workOrderItemList);
        log.info("入库完成，共生成{}张入库明细", outWorkOrderItemList.size());
    }

    @Override
    public boolean saveOrUpdate(WorkOrderItem workOrderItem) {
        //数据库中是Long类型，不能存空值
        if (StringUtils.isBlank(workOrderItem.getLineId())) {
            workOrderItem.setLineId(null);
        }
        if (StringUtils.isBlank(workOrderItem.getStockId())) {
            workOrderItem.setStockId(null);
        }
        if (workOrderItem.getPackageQty() <=0 ) {
            throw new BusinessException("包装数量不能小于等于0");
        }

        // 修改的是包
        if ("1".equals(workOrderItem.getMatrType())) {
            super.saveOrUpdate(workOrderItem);

            // 包明细配置
            List<PackTempletItem> packTempletItem = packTempletItemService.list(new QueryWrapper<PackTempletItem>().eq("pack_templet_id", workOrderItem.getPackId()));
            if (packTempletItem != null && packTempletItem.size() > 0) {
                Map<String,List<PackTempletItem>> packTempletItemGroupByMatrId = packTempletItem.stream()
                        .collect(Collectors.groupingBy(PackTempletItem::getMatrId));
                //包对应的入库明细, 重新计算包内耗材数量及金额
                List<WorkOrderItem> workOrderItemDtlList = this.list(Wrappers.<WorkOrderItem>query().eq("pack_item_id",workOrderItem.getId()).isNotNull("pack_item_id"));
                if (workOrderItemDtlList != null && workOrderItemDtlList.size() > 0) {
                    for(WorkOrderItem itemDtl : workOrderItemDtlList) {
                        if (packTempletItemGroupByMatrId.containsKey(itemDtl.getMatrId())) {
                            itemDtl.setPackageQty(packTempletItemGroupByMatrId.get(itemDtl.getMatrId()).get(0).getPackageQty() * workOrderItem.getPackageQty());
                            itemDtl.setSkuQty(itemDtl.getPackageRate() * itemDtl.getPackageQty());
                            itemDtl.setAmount(itemDtl.getSkuQty() * itemDtl.getSkuPrice());
                            itemDtl.setExpDate(workOrderItem.getExpDate());
                            itemDtl.setMfgDate(workOrderItem.getMfgDate());
                            itemDtl.setSterilizationDate(workOrderItem.getSterilizationDate());//灭菌日期
                            itemDtl.setSterilizationIndate(workOrderItem.getSterilizationIndate());//灭菌有效期
                            itemDtl.setLot(workOrderItem.getLot());
                        }
                    }
                    this.updateBatchById(workOrderItemDtlList);
                }
            }

            //重刷一下订单总价
            workOrderService.calculateOrderPrice(workOrderItem.getWorkOrderId());

            return true;
        }

        boolean flagOmoc = matrService.getOne(Wrappers.<Matr>query().eq("id",workOrderItem.getMatrId())).getFlagOmoc();
        if (!flagOmoc && workOrderItem.getPackageQty() > Integer.parseInt(ParameterUtils.getSystemInPackageMax())){
            throw new BusinessException("包装数量已超过系统限制数量【"+Integer.parseInt(ParameterUtils.getSystemInPackageMax())+"】，请修改");
        }

        if (DateUtils.compareDate(workOrderItem.getExpDate(), new Date())) {
            throw new BusinessException("当前耗材【%s】效期已过期", workOrderItem.getMatrName());
        }
        super.saveOrUpdate(workOrderItem);

        //重刷一下订单总价
        workOrderService.calculateOrderPrice(workOrderItem.getWorkOrderId());

        return true;
    }



    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        List<String> workOrderIds = this.listObjs(Wrappers.<WorkOrderItem>query()
                        .select("work_order_id").in("id", idList).groupBy("work_order_id"),
                v -> v.toString());

        Boolean boolResult = this.removeByIds(idList);
        // 删除对应的包明细
        this.remove(Wrappers.<WorkOrderItem>query().in("pack_item_id",idList).isNotNull("pack_item_id"));
        if (workOrderIds.size() > 0) { //重刷一下订单总价
            workOrderService.calculateOrderPrice(workOrderIds.get(0));
        }
        return boolResult;
    }



    @Override
    public List<WorkOrderItem> getLineId(String workOrderItemId, String workOrderId){
        List<WorkOrderItem> stockList = list(Wrappers.<WorkOrderItem>query()
                .eq("id",workOrderItemId)
                .eq("work_order_id",workOrderId));
        return stockList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addByPackTemp(StockByPackTempDTO stockByPackTempDTO) {
        if (CollectionUtils.isEmpty(stockByPackTempDTO.getPackTemplets())) {
            throw new BusinessException("请选择跟台包！");
        }
        if (org.apache.commons.lang3.StringUtils.isBlank(stockByPackTempDTO.getWorkOrderId())) {
            throw new BusinessException("当前入库主单信息未保存，请检查！");
        }
        //日期逻辑处理
        if (stockByPackTempDTO.getSterilizationDate().getTime() < stockByPackTempDTO.getMfgDate().getTime()) {
            throw new BusinessException("灭菌日期不能小于生产日期，请检查！");
        }

        if (stockByPackTempDTO.getSterilizationIndate().getTime() < new Date().getTime()) {
            throw new BusinessException("灭菌有效期不能小于当前日期，请检查！");
        }

        //获取包模板所有id集合
        List<String> packTempletIds = stockByPackTempDTO.getPackTemplets().stream().map(item -> item.getId()).collect(Collectors.toList());
        //查询模板信息
        List<PackTemplet> packTemplets = packTempletService.list(new QueryWrapper<PackTemplet>().in("id", packTempletIds));
        List<WorkOrderItem> workOrderItemList = new ArrayList<>();
        packTemplets.forEach(item->{
            WorkOrderItem  workOrderPack = new WorkOrderItem();
            workOrderPack.setWorkOrderId(stockByPackTempDTO.getWorkOrderId()); //主表id
            workOrderPack.setLocationId(stockByPackTempDTO.getLocationId());//库位id
            workOrderPack.setLocationName(stockByPackTempDTO.getLocationName());//库位名称
            workOrderPack.setExpDate(stockByPackTempDTO.getExpDate());
            workOrderPack.setMfgDate(stockByPackTempDTO.getMfgDate());
            workOrderPack.setLot(stockByPackTempDTO.getLot());
            workOrderPack.setSterilizationDate(stockByPackTempDTO.getSterilizationDate());//灭菌日期
            workOrderPack.setSterilizationIndate(stockByPackTempDTO.getSterilizationIndate());//灭菌有效期
            workOrderPack.setMatrName(item.getName());//名称
            workOrderPack.setPackId(item.getId());
            workOrderPack.setAmount(item.getAmount());
            workOrderPack.setMatrType("1");//跟台包
            workOrderPack.setMatrId("-1");//跟台包默认耗材id为-1
            workOrderPack.setMatrSpec("无");
            workOrderPack.setPackageUnit("");
            workOrderPack.setPackageQty(1.0);
            workOrderPack.setSkuPrice(item.getAmount());
            workOrderPack.setSkuQty(1.0);
            workOrderPack.setSkuUnit("包");
            workOrderPack.setPackageUnit("包");
            boolean success = this.save(workOrderPack);
            if (success){
                //根据模板主表id查询所有明细表
                String workOrderItemId = workOrderPack.getId();
                List<PackTempletItem> packTempletItem = packTempletItemService.list(new QueryWrapper<PackTempletItem>().eq("pack_templet_id", item.getId()));
                if (CollectionUtils.isEmpty(packTempletItem)) {
                    throw new BusinessException("跟台包%s内未维护耗材，请检查！", item.getName());
                }
                packTempletItem.stream().forEach(s->{
                WorkOrderItem workOrderItem = new WorkOrderItem();
                BeanUtils.copyProperties(s, workOrderItem);
                workOrderItem.setId(null);
                workOrderItem.setPackItemId(workOrderItemId);   //pack_item_id保存跟台包WorkOrderItem 入库明细表id
                workOrderItem.setWorkOrderId(stockByPackTempDTO.getWorkOrderId()); //跟台包WorkOrder 入库主表id
                workOrderItem.setLocationId(stockByPackTempDTO.getLocationId());//库位id
                workOrderItem.setLocationName(stockByPackTempDTO.getLocationName());//库位名称
                workOrderItem.setSkuPrice(s.getAmount()/ s.getSkuQty());  //价格
                workOrderItem.setExpDate(stockByPackTempDTO.getExpDate());
                workOrderItem.setMfgDate(stockByPackTempDTO.getMfgDate());
                workOrderItem.setSterilizationDate(stockByPackTempDTO.getSterilizationDate());//灭菌日期
                workOrderItem.setSterilizationIndate(stockByPackTempDTO.getSterilizationIndate());//灭菌有效期
                workOrderItem.setLot(stockByPackTempDTO.getLot());
                workOrderItemList.add(workOrderItem);
                });
            }
        });

        //是否禁用耗材校验-跟台包入库
        matrPassUtil.ckeckMatrPass("warehousing", workOrderItemList.stream().map(WorkOrderItem::getMatrId).collect(Collectors.toList()));
        updataAmount(stockByPackTempDTO.getWorkOrderId());
        return super.saveOrUpdateBatch(workOrderItemList);
    }

    @Override
    public void updateQty(WorkOrderItem workOrderItem) {
        WorkOrderItem item = this.baseMapper.selectById(workOrderItem.getPackItemId());
        PackTempletItem packTempletItem = packTempletItemService.getOne(new QueryWrapper<PackTempletItem>().select("sku_qty", "package_qty")
                .eq("pack_templet_id", item.getPackId())
                .eq("matr_id", workOrderItem.getMatrId()));
        this.update(Wrappers.<WorkOrderItem>update()
                .set("package_qty", workOrderItem.getPackageQty())
                .set("sku_qty", workOrderItem.getPackageQty() * (packTempletItem.getSkuQty() / packTempletItem.getPackageQty()))
                .set("amount", workOrderItem.getPackageQty() * (packTempletItem.getSkuQty() / packTempletItem.getPackageQty()) * workOrderItem.getSkuPrice())
                .eq("id", workOrderItem.getId()));
        //更新入库明细总金额
        updateOrderItemAmount(workOrderItem.getPackItemId());
        //更新入库主表总金额
        updataAmount(workOrderItem.getWorkOrderId());
    }

    @Override
    public void deletePackage(String id) {
        WorkOrderItem workOrderItem = this.getById(id);
        if (workOrderItem == null) {
            throw new BusinessException(String.format("未找到id为%s跟台包中", id));
        }
        List<WorkOrderItem> workOrderItems = this.list(new QueryWrapper<WorkOrderItem>().select("id").eq("pack_item_id", id));
        if (workOrderItems.isEmpty()) {
            this.removeById(id);
        } else {
            List<String> ids = workOrderItems.stream().map(s -> s.getId()).collect(Collectors.toList());
            this.removeByIds(ids);
            this.removeById(id);
        }
        updataAmount(workOrderItem.getWorkOrderId());
    }


    @Override
    public void deleteMatr(String id) {
        WorkOrderItem workOrderItem = this.getById(id);
        if (workOrderItem == null) {
            throw new BusinessException(String.format("在跟台包中未找到id为%s相关的耗材", id));
        }
        boolean success = this.removeById(id);
        if (success) {
            updateOrderItemAmount(workOrderItem.getPackItemId());
            updataAmount(workOrderItem.getWorkOrderId());
        }

    }

    /**
     * 修改 WorkOrderItem表中包金额及单品价格
     * @param packItemId
     */
    private void updateOrderItemAmount(String packItemId) {
        Map<String, Object> map = this.getMap(new QueryWrapper<WorkOrderItem>().select("sum(amount) as amount").eq("pack_item_id", packItemId));
        this.update(Wrappers.<WorkOrderItem>update()
                .set("amount", map.get("amount") == null ? 0 : map.get("amount"))
                .set("sku_price", map.get("amount") == null ? 0 : map.get("amount"))
                .eq("id", packItemId));
    }

    /**
     * 修改 WorkOrder表中包金额及单品价格
     *
     * @param workOrderId
     */
    private void updataAmount(String workOrderId) {
        Map<String, Object> workOrderMap = this.getMap(new QueryWrapper<WorkOrderItem>().select("sum(amount) as amount")
                .eq("work_order_id", workOrderId)
                .eq("matr_type", "1"));
        workOrderService.update(Wrappers.<WorkOrder>update()
                .set("amount", workOrderMap.get("amount") == null ? 0 : workOrderMap.get("amount"))
                .eq("id", workOrderId));
    }

    @Override
    public Page<WorkOrderItem> inorderItemPage(QueryContext context) {
        return baseMapper.page(context.getPage(), context.getWrapper(), context.getParams());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void splitOrderItem(WorkOrderItem workOrderItem) {
        MatrUnit matrUnit = matrUnitMapper.selectOne(new QueryWrapper<MatrUnit>().eq("matr_id", workOrderItem.getMatrId())
                .eq("unit", workOrderItem.getPackageUnit()).last("LIMIT 1"));
        if (matrUnit == null) {
            throw new BusinessException(String.format("在耗材%s中未找到相关的单位", workOrderItem.getMatrSpec()));
        }
        List<WorkOrderItem> items = new ArrayList<>();
        MatrUnit baseMatrUnit = matrUnitMapper.selectOne(new QueryWrapper<MatrUnit>().eq("matr_id",workOrderItem.getMatrId())
                .eq("flag_base","1").last("LIMIT 1"));
        if (workOrderItem.getSkuQty()<matrUnit.getRate()){
            workOrderItem.setPackageQty(workOrderItem.getSkuQty()).setPackageUnit(baseMatrUnit.getUnit());
            items.add(workOrderItem);
        }else {
            double floorItem = Math.floor(workOrderItem.getSkuQty() / matrUnit.getRate());
            double splitItem = workOrderItem.getSkuQty() - (matrUnit.getRate() * floorItem);
            workOrderItem.setPackageQty(floorItem).setPackageUnit(matrUnit.getUnit())
                    .setSkuQty((matrUnit.getRate() * floorItem))
                    .setAmount((matrUnit.getRate() * floorItem)*workOrderItem.getSkuPrice());
            WorkOrderItem newItem = new WorkOrderItem();
            BeanUtils.copyProperties(workOrderItem, newItem);
            newItem.setId(null);
            newItem.setPackageQty(splitItem).setPackageUnit(baseMatrUnit.getUnit()).setSkuQty(splitItem)
                    .setAmount(splitItem * newItem.getSkuPrice());
            items.add(workOrderItem);
            items.add(newItem);
        }
        this.saveOrUpdateBatch(items);
    }

    @Override
    public void saveOrderItemByOrthScan(OrthWiDTO orthWiDTO, WorkOrder workOrder, String warehouseId, Location location, String packItemId, double sumOrthWiItemQty) {
        if (CollectionUtils.isEmpty(orthWiDTO.getItems())) {
            return;
        }
        if (workOrder.getFlowStatus() != null && !GlobalConsts.FLOW_START_VALUE.equals(workOrder.getFlowStatus())) {
            throw new BusinessException("当前单据已被审核，请勿操作！");
        }
        List<WorkOrderItem> workOrderItems = this.list(new QueryWrapper<WorkOrderItem>().eq("work_order_id", workOrder.getId()));
        double sumQty = workOrderItems.stream().filter(workOrderItem -> "0".equals(workOrderItem.getMatrType())).mapToDouble(WorkOrderItem::getSkuQty).sum();
        if (sumQty + sumOrthWiItemQty > orthWiDTO.getTotalQty()) {
            throw new BusinessException("已入库数量：%s + 传入数量：%s 之和大于入库总数：%s,请检查！", sumQty, sumOrthWiItemQty, orthWiDTO.getTotalQty());
        }
        List<WorkOrderItem> packageList = workOrderItems.stream().filter(workOrderItem -> orthWiDTO.getPackageCode().equals(workOrderItem.getPackId())).collect(Collectors.toList());
        if (packageList.size() > 1) {
            throw new BusinessException("当前单据:%s,已存在多个跟台包，包编码为:%s", orthWiDTO.getOipWiSn(), orthWiDTO.getPackageCode());
        }
        if (packItemId == null) {
            packItemId = packageList.stream().findFirst().get().getId();
        }
        //是否重复
        orthWiDTO.getItems().forEach(ob1 -> {
            long goodsCodeNum = orthWiDTO.getItems().stream().filter(ob2 -> ob2.getGoodsCode().equals(ob1.getGoodsCode())).count();
            if (goodsCodeNum > 1) throw new BusinessException("耗材编码【%s】重复%s个，请检查", ob1.getGoodsCode(), goodsCodeNum);
        });
        List<WorkOrderItem> workOrderItemList = new ArrayList<>();
        for (OrthWiItemDTO item : orthWiDTO.getItems()) {
            Optional.ofNullable(item.getGoodsCode()).orElseThrow(() -> new BusinessException("耗材编码为空，请检查！"));

            Matr matr = matrService.getById(item.getGoodsCode());
            Optional.ofNullable(matr).orElseThrow(() -> new BusinessException("耗材编码：%s 未与系统耗材对码，请检查！", item.getGoodsCode()));

            MatrUnit matrUnit = matrUnitMapper.selectOne(new QueryWrapper<MatrUnit>().eq("flag_base", true).eq("matr_id", item.getGoodsCode()));

            List<WorkOrderItem> matritemList = workOrderItems.stream().filter(workOrderItem -> item.getGoodsCode().equals(workOrderItem.getMatrId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(matritemList)) {
                WorkOrderItem workOrderItem = new WorkOrderItem();
                workOrderItem.setAmount(UtilNum.getDouble(matr.getSkuPrice() * item.getQty()))
                        .setCertificateNo(matr.getCertificateNo())
                        .setExpDate(new Date())
                        .setMatrId(matr.getId())
                        .setMfgDate(new Date())
                        .setMatrName(matr.getName())
                        .setMatrSpec(item.getGoodsSpec())
                        .setLot(orthWiDTO.getBatch())
                        .setPackageUnit(matrUnit.getUnit())
                        .setPackageQty(item.getQty())
                        .setSkuPriceSp(matr.getSkuPrice())
                        .setSkuPrice(matr.getSkuPrice())
                        .setSkuQty(item.getQty())
                        .setSkuUnit(matr.getSkuUnit())
                        .setLocationId(location.getId())
                        .setLocationName(location.getName())
                        .setMfgName(matr.getMfgName())
                        .setSterilizationDate(new Date())
                        .setWorkOrderId(workOrder.getId())
                        .setPackItemId(packItemId)
                        .setUdi(item.getUdi() != null ? item.getUdi() : "");
                workOrderItemList.add(workOrderItem);
            } else {
                if (matritemList.size() > 1) {
                    throw new BusinessException("耗材编码为:%s,存在重复耗材明细,当前包编码为:%s,请检查！", orthWiDTO.getOipWiSn(), orthWiDTO.getPackageCode());
                }
                for (WorkOrderItem workOrderItem : matritemList) {
                    workOrderItem.setSkuQty(workOrderItem.getSkuQty() + item.getQty());
                    workOrderItem.setPackageQty(workOrderItem.getPackageQty() + item.getQty());
                    workOrderItem.setAmount((workOrderItem.getPackageQty() + item.getQty()) * workOrderItem.getSkuPrice());
                    workOrderItemList.add(workOrderItem);
                }
            }
        }

        super.saveOrUpdateBatch(workOrderItemList);
        updateOrderItemAmount(packItemId);
        updataAmount(workOrder.getId());
    }


    /**
     * 下载Excel模版
     * @param response
     * @param deliveryId
     */
    @Override
    public void downloadExcelTemp(HttpServletResponse response, String deliveryId) {
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        WorkOrderItem orderItem = inOrderItemMapper.selectById(deliveryId);
        String fileName = StrUtil.format("发货明细_{}_{}.xls",DateUtils.format(DateUtils.now(),DateUtils.YYYYMMDDHHMMSS_PATTER));
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        }

        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("发货明细");
        sheet.protectSheet("123456");
        int rowNextNum = 0;

        List<ExportHeadDTONew> exportHeadList = getExcelHead();
        //表头列-一级
        ExportHeadDTONew exportHeadDTO = null;
        HSSFRow row;
        HSSFCell cell;
        HSSFCellStyle cellStyle;
        HSSFFont font;
        HSSFRichTextString richTextString = null;
        HSSFCellStyle cellStyleTitle;
        cellStyleTitle = workbook.createCellStyle();
        //水平居中
//        cellStyleTitle.setAlignment(HorizontalAlignment.CENTER);

        font = workbook.createFont();
        //字体大小
        font.setFontHeightInPoints((short) 14);
//        font.setBold(true);   //字体加粗
        cellStyleTitle.setFont(font);

        //单元格锁定的样式
        HSSFCellStyle lockstyle = workbook.createCellStyle();
        lockstyle.setLocked(true);

        //单元格锁定的样式
        HSSFCellStyle unlockstyle = workbook.createCellStyle();
        unlockstyle.setLocked(false);
//        unlockstyle.setBorderBottom(BorderStyle.THIN); //底部边框
        unlockstyle.setBottomBorderColor(IndexedColors.GREEN.getIndex());//底部边框颜色

//        unlockstyle.setBorderTop(BorderStyle.THIN); //底部边框
        unlockstyle.setTopBorderColor(IndexedColors.GREEN.getIndex());//底部边框颜色

//        unlockstyle.setBorderLeft(BorderStyle.THIN); //底部边框
        unlockstyle.setLeftBorderColor(IndexedColors.GREEN.getIndex());//底部边框颜色

//        unlockstyle.setBorderRight(BorderStyle.THIN); //底部边框
        unlockstyle.setRightBorderColor(IndexedColors.GREEN.getIndex());//底部边框颜色

        row = sheet.createRow(rowNextNum);
        int cellIndex = 0;
        for (int i = 0; i < exportHeadList.size(); i++) {
            exportHeadDTO = exportHeadList.get(i);
            cell = row.createCell(cellIndex);
            richTextString = new HSSFRichTextString(exportHeadDTO.getText());
            cell.setCellValue(richTextString);

            cell.setCellStyle(cellStyleTitle);

            //改行跨列
            if (exportHeadDTO.getColspan() > 1){

                sheet.addMergedRegion(new CellRangeAddress(rowNextNum, rowNextNum, cellIndex, cellIndex+(exportHeadDTO.getColspan()-1)));
                cellIndex+=exportHeadDTO.getColspan();
            }else {
                cellIndex++;
            }

            //cell宽度
            sheet.setColumnWidth(i, (int) (UtilCommon.getStr(exportHeadDTO.getText(), "").getBytes().length * 1.2d * 256 > 12 * 256 ? UtilCommon.getStr(exportHeadDTO.getText(), "").getBytes().length * 1.2d * 256 : 12 * 256));
        }
        rowNextNum++;

        List<WorkOrderItem> deliveryItemList = this.baseMapper.selectList(Wrappers.<WorkOrderItem>query().eq("delivery_id", deliveryId));
        JSONArray itemListJson = JSONArray.parseArray(JSONArray.toJSONString(deliveryItemList));
        JSONObject itemJson;
        HSSFCell cellData;
        for (Object json : itemListJson) {
            row = sheet.createRow(rowNextNum);
            itemJson = (JSONObject) json;
            for (int i = 0; i < exportHeadList.size(); i++) {
                exportHeadDTO = exportHeadList.get(i);
                String value = itemJson.get(exportHeadDTO.getName()) + "";
                richTextString = new HSSFRichTextString(UtilCommon.getStr(value, ""));
                cellData = row.createCell(i);
                cellData.setCellValue(richTextString);
                if (exportHeadDTO.isReadonly()) {
                    cellData.setCellStyle(lockstyle);
                } else {
                    cellData.setCellStyle(unlockstyle);
                }
            }
            rowNextNum++;
        }

        OutputStream os1 = null;
        FileUtils.mkdirs(resPath + "download");
        String tmpFilePath = resPath + "download/"+fileName;
        File tmpFile = new File(tmpFilePath);
        byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        OutputStream os2 = null;

        try {
            os1 = new FileOutputStream(tmpFile);
            workbook.write(os1);

            os2 = response.getOutputStream();
            bis = new BufferedInputStream(new FileInputStream(tmpFile));
            int i = bis.read(buff);
            while (i != -1) {
                os2.write(buff, 0, buff.length);
                os2.flush();
                i = bis.read(buff);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 导入Excel数据的操作
     * @param file
     * @param deliveryId
     * @return
     */
    @Override
    public ImportResult importDtl(MultipartFile file, String deliveryId) {
        return null;
    }

    private List<ExportHeadDTONew> getExcelHead() {
        List<ExportHeadDTONew> exportHeadList = new ArrayList<ExportHeadDTONew>();
        ExportHeadDTONew headDTO;

        headDTO = new ExportHeadDTONew();
        headDTO.setName("matrName").setText("商品名称").setReadonly(true).setCellIndex(0);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("hrpCode").setText("商品编码").setReadonly(true).setCellIndex(1);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("matrSpec").setText("规格").setReadonly(true).setCellIndex(2);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("packageUnit").setText("包装单位").setReadonly(true).setCellIndex(3);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("packageQty").setText("包装数量").setReadonly(true).setCellIndex(4);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("amount").setText("金额").setReadonly(true).setCellIndex(5);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("lot").setText("批次").setCellIndex(7).setRequired(true);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("expDate").setText("效期").setCellIndex(8).setDate(true).setDatePattern(DateUtils.DEFAULT_PATTER_YMD);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("mfgDate").setText("生产日期").setCellIndex(9).setDate(true).setDatePattern(DateUtils.DEFAULT_PATTER_YMD);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("mfgSn").setText("厂家序号").setCellIndex(10);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("sterilizationDate").setText("灭菌日期").setCellIndex(11);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("udi").setText("商品原厂码(udi)").setCellIndex(12);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("sterilizationIndate").setText("灭菌效期").setCellIndex(11);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("mfgName").setText("生产厂家").setReadonly(true).setCellIndex(14);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("skuPrice").setText("单品价格").setReadonly(true).setCellIndex(13);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("skuQty").setText("单品数量").setReadonly(true).setCellIndex(13);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("certificateNo").setText("注册证号").setReadonly(true).setCellIndex(13);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("flagCenterPurchase").setText("常备耗材").setReadonly(true).setCellIndex(15);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("flagGys").setText("是否供应室").setReadonly(true).setCellIndex(16).setPk(true);
        exportHeadList.add(headDTO);

        headDTO = new ExportHeadDTONew();
        headDTO.setName("supplierName").setText("供应商名称").setReadonly(true).setCellIndex(16).setPk(true);
        exportHeadList.add(headDTO);

        return exportHeadList;
    }
}
